;;;; backgammon-game.lisp

(in-package #:gamao-impl)

(defclass backgammon-gameplay-mixin (reuse-first-dice-mixin standard-gameplay-mixin)
  ())

(defclass jacoby-mixin ()
  ()
  (:documentation "Jacoby rule to be applied on top of backgammon-checker-play-rules"))

(defmethod checker-position-result ((rule backgammon-checker-play-rules) checker-position player)
  (if (= (checker-position-checkers-at checker-position :off player) +checker-count+)
      (let ((opponent (opponent player)))
        (cond ((plusp (checker-position-checkers-at checker-position :off opponent)) :single)
              ((or (plusp (checker-position-checkers-at checker-position :bar opponent))
                   (loop for point from 19 to 24 
                         thereis (plusp (checker-position-checkers-at checker-position (players-point point opponent) opponent))))
               :backgammon)
              (t :gammon)))
      nil))

(defmethod checker-position-result ((game jacoby-mixin) checker-position player)
  (let ((raw-result (call-next-method)))
    (if (null raw-result)
        raw-result
        (let ((cube (cube-value game)))
          (if (or (null cube) (= cube 1))
              :single
              raw-result)))))

(defclass backgammon-game-score-mixin ()
  ())

(defmethod game-score ((game backgammon-game-score-mixin))
  (let* ((result (game-result game)))
    (if (null result)
        0
        (let ((cube (or (cube-value game) 1)))
          (* cube (ecase result
                    (:single 1)
                    (:gammon 2)
                    (:backgammon 3)))))))

(defclass unsafe-backgammon-mixin (backgammon-game-score-mixin
                                   backgammon-checker-play-rules
                                   backgammon-gameplay-mixin
                                   standard-legality-mixin
                                   standard-game-actions-mixin)
  ())

(defclass unsafe-backgammon-with-jacoby-mixin (jacoby-mixin unsafe-backgammon-mixin)
  ())

(defclass backgammon-mixin (rule-abiding-game-mixin unsafe-backgammon-mixin)
  ())

(defclass backgammon-with-jacoby-mixin (rule-abiding-game-mixin unsafe-backgammon-with-jacoby-mixin)
  ())

(defclass backgammon-game (backgammon-mixin board simple-checker-game)
  ())

(defclass backgammon-game-with-jacoby (backgammon-with-jacoby-mixin board simple-checker-game)
  ())

(defmethod simple-checker-game-unclassify-position ((game backgammon-checker-play-rules) position)
  (checker-position position))

(defmethod simple-checker-game-classify-board ((game backgammon-checker-play-rules))
  (classify-checker-position (checkers game) (current-player game) (die1 game) (die2 game) game))

(defmethod dice-count ((position rich-checker-position))
  (rcp-dice-count position))
